<?php if (!defined('BASE')) {die('No direct file access.');}

//********************************
//	File:		database.php
//	Author:		Philip Pryce
//	Date:		20th July 2008
//	Comments:	A database class to make interacting with the database more exciting.
//********************************


class Database {
	
	private $connection;
	private $config;
	
	
	// -------
	// lets load up the configuration and get started.
	// -------
	function __construct () {
		
		$SM = getInstance();
		$SM->config->load('database');
		$this->config = $SM->config->get('database');
		$SM->config->remove('database');
		unset($SM);
		
		$this->connect();
		
	}
	
	// -------
	// Connects to the database set in your configuration.
	// -------
	function connect () {
		
		// lets connect!
		$this->connection = new mysqli(
			$this->config['host'],
			$this->config['username'],
			$this->config['password'],
			$this->config['database']
		);
		
		// No password here thank you.
		unset($this->config['password']);
	}
	
	// -------
	// Escapes most stuff safely.
	// -------
	
	function escape($str) {	
		switch (gettype($str)) {
			case 'string':
				$str = "'".$this->escapeStr($str)."'";
				break;
				
			case 'boolean':
				$str = ($str === FALSE) ? 0 : 1;
				break;
				
			default:
				$str = ($str === NULL) ? 'NULL' : $str;
				break;
		}		

		return $str;
	}
	
	// -------
	// Escapes the string safely
	// -------
	function escapeStr($str) {
		if (function_exists('mysqli_real_escape_string') AND is_object($this->connection)) {
			return mysqli_real_escape_string($this->connection, $str);
		}
		elseif (function_exists('mysql_escape_string')) {
			return mysql_escape_string($str);
		}
		else {
			return addslashes($str);
		}
	}
	
	// -------
	// this function will take any "?" found in SQL querys and replace it with
	// a value from inside an array incrementally.
	// -------
	function replaceBinds ($sql, $binds) {
		
		$bind_marker = '?';
		
		if (strpos($sql, $bind_marker) === FALSE) {
			return $sql;
		}
		
		if (!is_array($binds)) {
			$binds = array($binds);
		}
		
		// Explode the SQL away from the markers
		$segments = explode($bind_marker, $sql);
		
		// With any luck there should be 1 less bind than the
		// count of all the segments, if theres more trim!
		if (count($binds) >= count($segments)) {
			$binds = array_slice($binds, 0, count($segments)-1);
		}

		// Construct the binded query
		$result = $segments[0];
		$i = 0;
		foreach ($binds as $bind) {
			$result .= $this->escape($bind);
			$result .= $segments[++$i];
		}
		
		return $result;
		
	}
	
	// -------
	// Query function, from basic querys, to powerful binds, we've got it!
	// -------
	function query ($sql, $binds=null, $object=true, $return=false) {
		
		if (is_array($binds)) {
			$sql = $this->replaceBinds($sql, $binds);
		}
		if ($return == true) {
			return $sql;
		}
			$query = $this->_raw($sql);
		
		$this->checkForError('query');
		
		if ($object && !$return) {
			$result = new Database_Result($query);
			return $result;
		}
		
		return $query;
	}
	
	function checkForError ($from) {
		if ($this->connection->error != '') {
			displayError(ERROR_FATAL, 'Database->' . $from, $this->connection->error);
		}
		return false;
	}
	
	// -------
	// execute a raw SQL command.
	// -------
	function _raw ($sql) {
		
		return $this->connection->query($sql);
		
	}
	
	
}

// This is for querys that return an object.
class Database_Result {
	
	var $result;
	
	function __construct ($result) {
		$this->result = $result;
	}
	
	function num_rows () {
		return $this->result->num_rows;
	}
	
	function rows () {
		$return = array();
		while ($row = $this->result->fetch_assoc()) {
			$return[] = $row;
		}
		return $return;
	}
	
	function _raw () {
		return $this->result;
	}
	
}

?>